package com.springboot.util;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import com.springboot.entity.Item;
import com.springboot.entity.Pipe;
import com.springboot.entity.Project;
import org.apache.commons.io.FilenameUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.web.multipart.MultipartFile;

import java.text.DecimalFormat;
import java.text.Format;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 实现Easy CCTV项目转换功能
 */
public class ConvertUtils {

    private static final List<String> codes = Arrays.asList("DEZ", "DE Z (J)", "CUZ", "OBZ", "INGZ", "SO", "JXZ", "LXZ", "RXZ", "MC", "SA");
    private static final Format format = new DecimalFormat("#00");

    private String myfile = null;
    private ThreadLocal<MultipartFile[]> local = new ThreadLocal<>();

    public Project initProject(MultipartFile[] files) {
        try {
            AtomicInteger index = new AtomicInteger(1);
            AtomicInteger photo = new AtomicInteger(1);
            Resource resource = new ClassPathResource("application.properties");
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
            myfile = properties.getProperty("myfile");
            local.set(files);

            MultipartFile file = AppHelper.getFile(files, "text/xml", "type");
            if (file == null)
                return null;

            Project project = new Project();
            project.setName(FilenameUtils.getBaseName(file.getOriginalFilename()));
            project.setSlope("N");
            project.setStandard("MSCC 2013");
            project.setState("未提交");

            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(file.getInputStream());
            Element root = document.getRootElement();

            List<Pipe> pipes = new ArrayList<>(root.elements("Survey").size());
            root.elementIterator().forEachRemaining((element) -> {
                Pipe pipe = initPipe(element, index, photo);
                pipe.setProject(project);
                pipes.add(pipe);
            });
            project.setPipes(pipes);
            return project;
        } catch (Exception e) {
            return null;
        } finally {
            local.remove();
        }
    }

    public Pipe initPipe(Element element, AtomicInteger index, AtomicInteger photo) {
        Pipe pipe = new Pipe();
        Element header = element.element("Header");

        pipe.setNo(index.getAndIncrement());
        pipe.setOperator(header.elementText("NameOfSurveyor"));
        pipe.setWorkorder(header.elementText("ContractorsJobRef"));
        pipe.setReference(header.elementText("PipelineLengthRef"));
        pipe.setPurposes("Structural Defects");
        pipe.setSlope("");
        pipe.setSloperef("");
        pipe.setYearlaid("");
        pipe.setDate(header.element("Date").getText());
        pipe.setTime(header.element("Time").getText());

        pipe.setDistrict1("");
        pipe.setDistrict2("");
        pipe.setDistrict3("");
        pipe.setRoadname(header.element("LocationStreet").getText());
        pipe.setHousenum("");
        pipe.setBuilding("");
        pipe.setDivision("");
        pipe.setAreacode("");

        pipe.setSmanholeno(header.element("StartNodeRef").getText());
        pipe.setFmanholeno(header.element("FinishNodeRef").getText());
        pipe.setUses(header.element("UseOfDrainSewer").getText());
        pipe.setDire(header.element("Direction").getText());
        pipe.setHsize(header.element("HeightDiameter").getText());
        pipe.setWsize(header.element("Width") == null ? "" : header.elementText("Width"));
        pipe.setShape(header.element("Shape").getText());
        pipe.setMater(header.element("Material").getText());
        pipe.setLining("");
        pipe.setPipelength(0.0);
        pipe.setTestlength(0.0);

        pipe.setSdepth("--");
        pipe.setScoverlevel("--");
        pipe.setSinvertlevel("--");
        pipe.setFdepth("--");
        pipe.setFcoverlevel("--");
        pipe.setFinvertlevel("--");
        pipe.setCategory("--");
        pipe.setCleaned(header.element("Precleaned").getText());
        pipe.setWeather(header.element("Weather").getText());
        pipe.setVideono(header.element("VideoImageFilename").getText());
        pipe.setComment("");

        pipe.setPipeid("");
        pipe.setReason("");
        pipe.setMethod("");

        List<Element> elements = element.element("Observations").elements();
        List<Item> items = new ArrayList<>(elements.size());
        elements.forEach(node -> {
            Item item = initItem(node, photo);
            item.setPipe(pipe);
            items.add(item);
        });
        double length = items.stream().mapToDouble(item -> Convert.toDouble(item.getDist())).max().orElse(0.0);
        pipe.setTestlength(length);
        pipe.setItems(items);
        return pipe;
    }

    public Item initItem(Element element, AtomicInteger photo) {
        Item item = new Item();
        item.setVideo(element.elementText("VideoRef"));
        if (element.element("PhotographRefs") != null)
            item.setPhoto(photo.getAndIncrement() + "");
        else
            item.setPhoto("");

        item.setDist(element.elementText("Distance"));
        if (element.element("ContinuousDefect") != null)
            item.setCont(element.elementText("ContinuousDefect"));

        String code = element.elementText("Code");
        if (codes.contains(code))
            item.setCode(code + "+");
        else
            item.setCode(code);

        if (element.element("Dimension1") != null)
            item.setDiam(element.elementText("Dimension1"));
        if (element.element("ClockRefAtFrom") != null) {
            Double data = Convert.toDouble(element.elementText("ClockRefAtFrom"), 0.0);
            item.setClockAt(format.format(data));
        }

        if (element.element("ClockRefAtFrom") != null && element.element("ClockRefTo") != null) {
            item.setClockAt("");
            Double data1 = Convert.toDouble(element.elementText("ClockRefAtFrom"), 0.0);
            Double data2 = Convert.toDouble(element.elementText("ClockRefTo"), 0.0);
            item.setClockTo(format.format(data1) + format.format(data2));
        }
        if (element.element("Percentage") != null)
            item.setPercent(element.elementText("Percentage"));
        // 缺少Intrusion（mm）暂时未能确定

        if (element.element("Remark") != null)
            item.setRemarks(element.elementText("Remark"));

        if (element.element("PhotographRefs") != null) {
            String filename = FilenameUtils.getBaseName(element.elementText("PhotographRefs"));
            MultipartFile file = AppHelper.getFile(local.get(), filename, "name");
            if (file != null) {
                AppHelper.move(file, FileUtil.file(myfile + "/itemImage/" + filename + ".png"));
                item.setPicture(filename);
            }
        }
        return item;
    }

}
